package com.fattyCorps.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fattyCorps.cache.PlayerCache;
import com.fattyCorps.config.gameConfig.GlobalConfig;
import com.fattyCorps.exception.gameException.CreatePlayerErrorException;
import com.fattyCorps.mapper.PlayerMapper;
import com.fattyCorps.mgr.event.EEvent;
import com.fattyCorps.mgr.event.EventMgr;
import com.fattyCorps.obj.cache.PlayerInfo;
import com.fattyCorps.obj.db.Player;
import com.fattyCorps.obj.msg.SRet;
import com.fattyCorps.obj.msg.server.SGetInfo;
import com.fattyCorps.utils.DateUtils;
import com.fattyCorps.utils.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;

@Service
@Slf4j
public class PlayerService {

    @Autowired
    PlayerMapper playerMapper;

    @Autowired
    PlayerCache playerCache;

    @Autowired
    HeroService heroService;

    @Autowired
    ItemService itemService;

    @Autowired
    GlobalConfig globalConfig;

    @Autowired
    MailService mailService;

    @Autowired
    EventMgr eventMgr;

    public int createPlayer(Integer accountId) {
        Integer initHead = globalConfig.getIntValue(GlobalConfig.PLAYER_INIT_HEAD);
        Integer initLv = globalConfig.getIntValue(GlobalConfig.PLAYER_INIT_LV);
        Integer initCoin = globalConfig.getIntValue(GlobalConfig.PLAYER_INIT_COIN);
        Integer initGuanqia = globalConfig.getIntValue(GlobalConfig.PLAYER_INIT_GUANQIA);

        Player playerInfo = new Player();
        playerInfo.setAccountId(accountId);

        playerInfo.setHead(initHead);
        playerInfo.setLv(initLv);
        playerInfo.setCoin(initCoin);
        playerInfo.setGuanqia(initGuanqia);
        playerInfo.setGlobalMailId(0);


        SimpleDateFormat df = new SimpleDateFormat(DateUtils.YYYY_MM_DD_HH_MM_SS);
        String initTimeStr = df.format(0);
        playerInfo.setLastFreeRollTime(initTimeStr);

        try {
            playerMapper.insert(playerInfo);
        } catch (Exception e) {
            log.error("getInfo error: accountId" + accountId);
            e.printStackTrace();
            throw new CreatePlayerErrorException();
        }

        // 初始账号赠送道具
        initPlayerItems(playerInfo);

        return playerInfo.getId();
    }

    // 获取用户基础信息
    public SRet getInfo(Integer accountId) {
        QueryWrapper<Player> wrapper = new QueryWrapper<>();
        wrapper.eq("account_id", accountId);
        Player playerDB = playerMapper.selectOne(wrapper);

        int playerId = playerDB == null ? createPlayer(accountId) : playerDB.getId();

        Player player = playerMapper.selectOne(wrapper);

        initCache(player);
        // 防止缓存变动过快返回了数据库的旧数据
        PlayerInfo playerInfo = playerCache.getPlayerInfo(player.getId());
        player = playerInfo.getBaseProp();

        // 登录时额外操作
        onPlayerLogin(playerInfo);

        String playerToken = JwtUtil.createPlayerToken(player.getId());

        // 向客户端返回角色信息
        SGetInfo sGetInfo = new SGetInfo();
        sGetInfo.setNickname(player.getNickname());
        sGetInfo.setHead(player.getHead());
        sGetInfo.setLv(player.getLv());
        sGetInfo.setCoin(player.getCoin());
        sGetInfo.setGuanqia(player.getGuanqia());
        sGetInfo.setNewToken(playerToken);

        return SRet.success(sGetInfo);
    }

    public boolean addCoin(Integer playerId, Integer coin) {
        PlayerInfo playerInfo = playerCache.getPlayerInfo(playerId);
        Player baseProp = playerInfo.getBaseProp();
        Integer curCoin = baseProp.getCoin();

        if (coin < 0) {
            //消耗
            if (curCoin < -coin) {
                //不足
                return false;
            }
        } else if (coin == 0) {
            return true;
        }

        Integer newCoin = curCoin + coin;
        baseProp.setCoin(newCoin);

        return true;
    }

    public Integer getCoin(Integer playerId) {
        PlayerInfo playerInfo = playerCache.getPlayerInfo(playerId);
        return playerInfo.getBaseProp().getCoin();
    }

    //读取数据库信息到缓存
    private void initCache(Player player) {
        //加载用户基础信息到缓存
        PlayerInfo playerInfo = playerCache.getPlayerInfo(player.getId(), false);
        if (playerInfo != null) {
            return;
        }
        playerInfo = new PlayerInfo();
        playerInfo.setBaseProp(player);

        playerInfo.setLastHeartBeatTime(System.currentTimeMillis());

//        //加载用户信息到缓存（注释代码已优化）
//        //加载用户英雄信息
//        heroService.initCache(playerInfo);
//        //加载用户道具信息
//        itemService.initCache(playerInfo);
//        //加载用户邮件信息
//        mailService.initCache(playerInfo);

        // 优化后
        playerCache.initPlayerCache(playerInfo);

//        //加载其他模块
//        playerCache.addPlayerInfo(playerInfo);
    }

    // 处理心跳
    public void procHeartBeat(Integer playerId) {
        PlayerInfo playerInfo = playerCache.getPlayerInfo(playerId);
        long curTime = System.currentTimeMillis();
        playerInfo.setLastHeartBeatTime(curTime);
    }

    // 创建角色时初始化用户身上的道具
    public void initPlayerItems(Player player) {
        String initItemStr = globalConfig.getStringValue(GlobalConfig.PLAYER_INIT_ITEMS);
        String[] split = initItemStr.split(",");
        for (int i = 0; i < split.length; i++) {
            Integer itemTypeID = Integer.valueOf(split[i]);
            i = i + 1;
            Integer itemNum = Integer.valueOf(split[i]);

            // 增加道具
            itemService.addItemInDB(player.getId(), itemTypeID, itemNum);
        }
    }

    public void onPlayerLogin(PlayerInfo playerInfo) {
        mailService.procGlobalMail(playerInfo);
    }

    public void passGuanQia(Integer playerId) {
        PlayerInfo playerInfo = playerCache.getPlayerInfo(playerId);

        // 先写个简单的，后续这里要做正确性判断
        playerInfo.getBaseProp().setGuanqia(playerInfo.getBaseProp().getGuanqia() + 1);


        eventMgr.sendEvent(EEvent.EVENT_UPDATE_GUANQIA, playerId, playerInfo.getBaseProp().getGuanqia());

        // 更新等级
        lvUp(playerId);
    }

    public void lvUp(Integer playerId) {
        PlayerInfo playerInfo = playerCache.getPlayerInfo(playerId);
        playerInfo.getBaseProp().setLv(playerInfo.getBaseProp().getLv() + 1);

        // 更新排行榜
        eventMgr.sendEvent(EEvent.EVENT_UPDATE_LV, playerId, playerInfo.getBaseProp().getLv());
    }
}
